home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / VBSamples / Common / DplayCon.frm < prev    next >
Text File  |  2001-10-08  |  42KB  |  1,065 lines

  1. VERSION 5.00
  2. Begin VB.Form DPlayConnect 
  3.    BorderStyle     =   3  'Fixed Dialog
  4.    Caption         =   "Multiplayer connect"
  5.    ClientHeight    =   3330
  6.    ClientLeft      =   45
  7.    ClientTop       =   330
  8.    ClientWidth     =   6345
  9.    Icon            =   "DplayCon.frx":0000
  10.    LinkTopic       =   "Form1"
  11.    MaxButton       =   0   'False
  12.    MinButton       =   0   'False
  13.    ScaleHeight     =   3330
  14.    ScaleWidth      =   6345
  15.    StartUpPosition =   3  'Windows Default
  16.    Begin VB.Frame fraWiz 
  17.       BorderStyle     =   0  'None
  18.       Height          =   3195
  19.       Index           =   1
  20.       Left            =   120
  21.       TabIndex        =   5
  22.       Top             =   60
  23.       Width           =   6195
  24.       Begin VB.CommandButton cmdCancelGame 
  25.          Caption         =   "Cancel"
  26.          Height          =   315
  27.          Left            =   5040
  28.          TabIndex        =   12
  29.          Top             =   2880
  30.          Width           =   1095
  31.       End
  32.       Begin VB.CommandButton cmdRefresh 
  33.          Caption         =   "S&tart Search"
  34.          Height          =   315
  35.          Left            =   5040
  36.          TabIndex        =   11
  37.          Top             =   60
  38.          Width           =   1095
  39.       End
  40.       Begin VB.CommandButton cmdJoin 
  41.          Caption         =   "&Join"
  42.          Height          =   315
  43.          Left            =   60
  44.          TabIndex        =   8
  45.          Top             =   2880
  46.          Width           =   1095
  47.       End
  48.       Begin VB.CommandButton cmdCreate 
  49.          Caption         =   "&Create"
  50.          Height          =   315
  51.          Left            =   1200
  52.          TabIndex        =   7
  53.          Top             =   2880
  54.          Width           =   1095
  55.       End
  56.       Begin VB.ListBox lstGames 
  57.          Height          =   2400
  58.          Left            =   60
  59.          TabIndex        =   6
  60.          Top             =   420
  61.          Width           =   6075
  62.       End
  63.       Begin VB.Label Label3 
  64.          BackStyle       =   0  'Transparent
  65.          Caption         =   "Click 'Start Search' to look for a session, or create one of your own."
  66.          Height          =   255
  67.          Left            =   60
  68.          TabIndex        =   25
  69.          Top             =   120
  70.          Width           =   4935
  71.       End
  72.    End
  73.    Begin VB.Frame fraWiz 
  74.       BorderStyle     =   0  'None
  75.       Height          =   3195
  76.       Index           =   0
  77.       Left            =   120
  78.       TabIndex        =   2
  79.       Top             =   60
  80.       Width           =   6195
  81.       Begin VB.CommandButton cmdCancel 
  82.          Cancel          =   -1  'True
  83.          Caption         =   "Cancel"
  84.          Height          =   315
  85.          Left            =   3900
  86.          TabIndex        =   10
  87.          Top             =   2760
  88.          Width           =   1095
  89.       End
  90.       Begin VB.CommandButton cmdOk 
  91.          Caption         =   "OK"
  92.          Default         =   -1  'True
  93.          Height          =   315
  94.          Left            =   5040
  95.          TabIndex        =   9
  96.          Top             =   2760
  97.          Width           =   1095
  98.       End
  99.       Begin VB.ListBox lstSP 
  100.          Height          =   1815
  101.          Left            =   60
  102.          TabIndex        =   4
  103.          Top             =   900
  104.          Width           =   6075
  105.       End
  106.       Begin VB.TextBox txtUserName 
  107.          Height          =   285
  108.          Left            =   60
  109.          TabIndex        =   1
  110.          Top             =   300
  111.          Width           =   6075
  112.       End
  113.       Begin VB.Label Label1 
  114.          BackStyle       =   0  'Transparent
  115.          Caption         =   "Select your ser&vice provider:"
  116.          Height          =   255
  117.          Index           =   1
  118.          Left            =   60
  119.          TabIndex        =   3
  120.          Top             =   660
  121.          Width           =   3915
  122.       End
  123.       Begin VB.Label Label1 
  124.          BackStyle       =   0  'Transparent
  125.          Caption         =   "&Player Name:"
  126.          Height          =   255
  127.          Index           =   0
  128.          Left            =   60
  129.          TabIndex        =   0
  130.          Top             =   60
  131.          Width           =   3915
  132.       End
  133.    End
  134.    Begin VB.Frame fraWiz 
  135.       BorderStyle     =   0  'None
  136.       Height          =   3195
  137.       Index           =   2
  138.       Left            =   120
  139.       TabIndex        =   13
  140.       Top             =   60
  141.       Width           =   6195
  142.       Begin VB.Frame Frame1 
  143.          Caption         =   "Extra Session Options"
  144.          Height          =   1995
  145.          Left            =   60
  146.          TabIndex        =   20
  147.          Top             =   660
  148.          Width           =   5955
  149.          Begin VB.CheckBox chkMigrate 
  150.             Alignment       =   1  'Right Justify
  151.             Caption         =   "Migrate &Host"
  152.             Height          =   255
  153.             Left            =   30
  154.             TabIndex        =   21
  155.             Top             =   600
  156.             Width           =   2895
  157.          End
  158.          Begin VB.TextBox txtUsers 
  159.             Height          =   285
  160.             Left            =   2490
  161.             TabIndex        =   19
  162.             Top             =   240
  163.             Width           =   435
  164.          End
  165.          Begin VB.Label Label1 
  166.             BackStyle       =   0  'Transparent
  167.             Caption         =   "N&umber of players in this session:"
  168.             Height          =   255
  169.             Index           =   2
  170.             Left            =   60
  171.             TabIndex        =   18
  172.             Top             =   285
  173.             Width           =   2355
  174.          End
  175.       End
  176.       Begin VB.TextBox txtGameName 
  177.          Height          =   285
  178.          Left            =   60
  179.          TabIndex        =   17
  180.          Top             =   300
  181.          Width           =   6075
  182.       End
  183.       Begin VB.CommandButton cmdOkCreate 
  184.          Caption         =   "OK"
  185.          Height          =   315
  186.          Left            =   5040
  187.          TabIndex        =   15
  188.          Top             =   2760
  189.          Width           =   1095
  190.       End
  191.       Begin VB.CommandButton cmdCancelCreate 
  192.          Caption         =   "Cancel"
  193.          Height          =   315
  194.          Left            =   3900
  195.          TabIndex        =   14
  196.          Top             =   2760
  197.          Width           =   1095
  198.       End
  199.       Begin VB.Label Label1 
  200.          BackStyle       =   0  'Transparent
  201.          Caption         =   "Please enter the session &name"
  202.          Height          =   255
  203.          Index           =   3
  204.          Left            =   60
  205.          TabIndex        =   16
  206.          Top             =   60
  207.          Width           =   2235
  208.       End
  209.    End
  210.    Begin VB.Timer tmrExpire 
  211.       Interval        =   500
  212.       Left            =   7500
  213.       Top             =   780
  214.    End
  215.    Begin VB.Frame fraWiz 
  216.       BorderStyle     =   0  'None
  217.       Height          =   3195
  218.       Index           =   3
  219.       Left            =   60
  220.       TabIndex        =   22
  221.       Top             =   60
  222.       Width           =   6195
  223.       Begin VB.CommandButton cmdCancelLobby 
  224.          Caption         =   "Cancel"
  225.          Height          =   315
  226.          Left            =   2340
  227.          TabIndex        =   24
  228.          Top             =   1500
  229.          Width           =   1455
  230.       End
  231.       Begin VB.Label Label2 
  232.          BackStyle       =   0  'Transparent
  233.          Caption         =   "Waiting for lobby connection"
  234.          Height          =   375
  235.          Left            =   2100
  236.          TabIndex        =   23
  237.          Top             =   1140
  238.          Width           =   2115
  239.       End
  240.    End
  241. End
  242. Attribute VB_Name = "DPlayConnect"
  243. Attribute VB_GlobalNameSpace = False
  244. Attribute VB_Creatable = False
  245. Attribute VB_PredeclaredId = True
  246. Attribute VB_Exposed = False
  247. Option Explicit
  248. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  249. '
  250. '  Copyright (C) 1999-2001 Microsoft Corporation.  All Rights Reserved.
  251. '
  252. '  File:       DPlayCon.frm
  253. '
  254. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  255. 'Sleep declare
  256. Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
  257. 'GetTickCount declare
  258. Private Declare Function GetTickCount Lib "kernel32" () As Long
  259. 'Declares for closing the form without waiting
  260. Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  261. Private Const WM_CLOSE = &H10
  262.  
  263. 'Host expire threshold constant
  264. Private Const HOST_EXPIRE_THRESHHOLD As Long = 2000
  265.  
  266. Private Type HostFound
  267.     AppDesc As DPN_APPLICATION_DESC
  268.     AddressHost As String
  269.     AddressDevice As String
  270.     TimeLastFound As Long
  271. End Type
  272.  
  273. Private Enum WizPanes
  274.     PickProtocol
  275.     CreateJoinGame
  276.     CreateNewGame
  277.     WaitForLobby
  278. End Enum
  279.  
  280. Private Enum SearchingButton
  281.     StartSearch
  282.     StopSearch
  283. End Enum
  284.  
  285. 'Internal DirectX variables
  286. Private moDPP As DirectPlay8Peer
  287. Private moDPC As DirectPlay8Client
  288. Private moDPA As DirectPlay8Address
  289. Private moDX As DirectX8
  290. Private moCallback As DirectPlay8Event
  291. Private moDPLA As DirectPlay8LobbiedApplication
  292.  
  293. 'App specific vars
  294. Private msGuid As String
  295. Private sUser As String
  296. Private mlSearch As SearchingButton
  297. Private sGameName As String
  298. Private mlMax As Long
  299. Private mlNumPlayers As Long
  300. Private mfComplete As Boolean
  301. Private mfHost As Boolean
  302. Private mlEnumAsync As Long
  303. Private mfGotEvent As Boolean
  304. Private mfDoneWiz As Boolean
  305.  
  306. Private mlLobbyClientID As Long
  307. Private mfCanUnload As Boolean
  308.  
  309. 'We need to keep track of the hosts we get
  310. Private moHosts() As HostFound
  311. Private mlHostCount As Long
  312. 'Declaration for our API
  313. Private Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
  314. Private mfDoneEnum As Boolean
  315. Private mfConnectComplete As Boolean
  316.  
  317. 'We need to implement the Event model for DirectPlay so we can receive callbacks
  318. Implements DirectPlay8Event
  319. Implements DirectPlay8LobbyEvent
  320.  
  321. Private Function StartWizard(oDX As DirectX8, sGuid As String, ByVal lMaxPlayers As Long, Optional oCallback As DirectPlay8Event = Nothing, Optional ByVal fAllowMigrateHost As Boolean = True) As Boolean
  322.     Dim lCount As Long, lIndex As Long
  323.     Dim dpn As DPN_SERVICE_PROVIDER_INFO
  324.     'Now we can start our connection
  325.     
  326.     mfCanUnload = False
  327.     mlSearch = StartSearch
  328.     mlHostCount = -1
  329.     
  330.     'First we need to keep track of our Peer Object, and app guid
  331.     Set moDX = oDX
  332.     Set moCallback = oCallback
  333.     msGuid = sGuid
  334.     mlMax = lMaxPlayers
  335.     
  336.     lIndex = GetSetting("VBDirectPlay", "Defaults", "SPListIndex", -1)
  337.     If Not (moDPP Is Nothing) Then
  338.         moDPP.RegisterMessageHandler Me
  339.         'First load our list of Service Providers into our box
  340.         For lCount = 1 To moDPP.GetCountServiceProviders
  341.             dpn = moDPP.GetServiceProvider(lCount)
  342.             lstSP.AddItem dpn.Name
  343.             'Pick the TCP/IP connection by default
  344.             If InStr(dpn.Name, "TCP") Then lstSP.ListIndex = lstSP.ListCount - 1
  345.         Next
  346.         If lstSP.ListIndex < 0 Then lstSP.ListIndex = 0
  347.     ElseIf Not (moDPC Is Nothing) Then
  348.         moDPC.RegisterMessageHandler Me
  349.         'First load our list of Service Providers into our box
  350.         For lCount = 1 To moDPC.GetCountServiceProviders
  351.             dpn = moDPC.GetServiceProvider(lCount)
  352.             lstSP.AddItem dpn.Name
  353.             'Pick the TCP/IP connection by default
  354.             If InStr(dpn.Name, "TCP") Then lstSP.ListIndex = lstSP.ListCount - 1
  355.         Next
  356.         If lstSP.ListIndex < 0 Then lstSP.ListIndex = 0
  357.     End If
  358.     If lIndex <> -1 And lIndex < lstSP.ListCount Then lstSP.ListIndex = lIndex
  359.     lstSP.AddItem "Wait for Lobby Connection..."
  360.     'Load the default Username for VBDirectPlay samples
  361.     sUser = GetSetting("VBDirectPlay", "Defaults", "UserName", vbNullString)
  362.     If sUser = vbNullString Then
  363.         'If there is not a default username, then pick the currently
  364.         'logged on username
  365.         sUser = Space$(255)
  366.         GetUserName sUser, 255
  367.         sUser = Left$(sUser, InStr(sUser, Chr$(0)) - 1)
  368.     End If
  369.     chkMigrate.Visible = fAllowMigrateHost
  370.     txtUserName.Text = sUser
  371.     ShowPane PickProtocol
  372.     Set moDPLA = dx.DirectPlayLobbiedApplicationCreate
  373.     'Init the register handler here
  374.     moDPLA.RegisterMessageHandler Me
  375.     'Register this app (in case it isn't registered already)
  376.     RegisterThisApp sGuid
  377.     'Show this screen
  378.     Me.Show vbModeless
  379.     'We have this loop here rather than just displaying the form as a modal
  380.     'dialog if we did just display the form as modal, it would not get a
  381.     'button in the toolbar, since it would have a parent window that wasn't visible
  382.     
  383.     'By displaying the window modeless, and going into a loop we get to have our
  384.     'icon on the taskbar, and keep the main form waiting until we are done in this form.
  385.     Do While Not mfDoneWiz
  386.         DoSleep 5 'Give other threads cpu time
  387.     Loop
  388.     'Get rid of the lobby interface if it isn't necessary
  389.     If mlLobbyClientID <> 0 Then
  390.         If Not (moDPP Is Nothing) Then
  391.             moDPP.RegisterLobby mlLobbyClientID, moDPLA, DPNLOBBY_UNREGISTER
  392.         ElseIf Not (moDPC Is Nothing) Then
  393.             moDPC.RegisterLobby mlLobbyClientID, moDPLA, DPNLOBBY_UNREGISTER
  394.         End If
  395.     End If
  396.     If Not (moDPLA Is Nothing) Then moDPLA.Close
  397.     Set moDPLA = Nothing
  398.     'Now we can return our success (or failure)
  399.     StartWizard = mfComplete
  400. End Function
  401.  
  402. Public Function StartClientConnectWizard(oDX As DirectX8, oDPC As DirectPlay8Client, sGuid As String, ByVal lMaxPlayers As Long, Optional oCallback As DirectPlay8Event = Nothing, Optional ByVal fAllowMigrateHost As Boolean = True) As Boolean
  403.     Set moDPP = Nothing
  404.     Set moDPC = oDPC
  405.     cmdCreate.Visible = False
  406.     StartClientConnectWizard = StartWizard(oDX, sGuid, lMaxPlayers, oCallback, fAllowMigrateHost)
  407. End Function
  408.  
  409. Public Function StartConnectWizard(oDX As DirectX8, oDPP As DirectPlay8Peer, sGuid As String, ByVal lMaxPlayers As Long, Optional oCallback As DirectPlay8Event = Nothing, Optional ByVal fAllowMigrateHost As Boolean = True) As Boolean
  410.     Set moDPC = Nothing
  411.     Set moDPP = oDPP
  412.     cmdCreate.Visible = True
  413.     StartConnectWizard = StartWizard(oDX, sGuid, lMaxPlayers, oCallback, fAllowMigrateHost)
  414. End Function
  415.  
  416. Public Sub CloseForm(oForm As Form)
  417.     'Anytime we need to close a form from within a DirectPlay callback
  418.     'we need to use this function.  The reason is that DirectPlay uses multiple
  419.     'threads to spawn all of it's messages back to the application.  However
  420.     'it cannot close down until all of it's threads have returned.
  421.     'If we attempt to simply call Unload Me in the callback, we will run into
  422.     'a deadlock instance, since the callback will be running on the DirectPlay
  423.     'thread waiting for the unload to finish, and the unload will be waiting
  424.     'for the DirectPlay thread to finish.
  425.     
  426.     'PostMessage puts the message on the queue for our form and returns immediately
  427.     'allowing the thread to finish
  428.     PostMessage oForm.hwnd, WM_CLOSE, 0, 0
  429. End Sub
  430.  
  431. Public Sub DoSleep(Optional ByVal lMilliSec As Long = 0)
  432.     'The DoSleep function allows other threads to have a time slice
  433.     'and still keeps the main VB thread alive (since DPlay callbacks
  434.     'run on separate threads outside of VB).
  435.     Sleep lMilliSec
  436.     DoEvents
  437. End Sub
  438.  
  439. Private Sub cmdCancel_Click()
  440.     Unload Me
  441. End Sub
  442.  
  443. Private Sub cmdCancelCreate_Click()
  444.     'If they click cancel here, just go back to the last step
  445.     ShowPane CreateJoinGame
  446. End Sub
  447.  
  448. Private Sub cmdCancelGame_Click()
  449.     'If they click cancel here, just go back to the first step
  450.     ShowPane PickProtocol
  451. End Sub
  452.  
  453. Private Sub cmdCancelLobby_Click()
  454.     'Don't wait any more.
  455.     moDPLA.SetAppAvailable False, 0
  456.     ShowPane PickProtocol
  457. End Sub
  458.  
  459. Private Sub cmdCreate_Click()
  460.     Dim sDefault As String
  461.     
  462.     'Here we should get our default
  463.     sDefault = GetSetting("VBDirectPlay", "Defaults", "GameName", vbNullString)
  464.     txtGameName.Text = sDefault
  465.     txtUsers.Text = CStr(mlMax)
  466.     chkMigrate.Value = Val(GetSetting("VBDirectPlay", "Defaults", "HostMigrate"))
  467.     'Show the create game screen
  468.     ShowPane CreateNewGame
  469. End Sub
  470.  
  471. Private Sub cmdJoin_Click()
  472.     Dim HostAddr As DirectPlay8Address
  473.     Dim DeviceAddr As DirectPlay8Address
  474.     
  475.     Dim dpApp As DPN_APPLICATION_DESC
  476.     
  477.     'You must select a game before you try to join one
  478.     If lstGames.ListIndex < 0 Then
  479.         MsgBox "You must first select a game from the list to join.", vbOKOnly Or vbInformation, "Select game."
  480.         Exit Sub
  481.     End If
  482.     
  483.     'Lets join the game
  484.     Dim pInfo As DPN_PLAYER_INFO
  485.     'Set up my peer info
  486.     pInfo.Name = sUser
  487.     pInfo.lInfoFlags = DPNINFO_NAME
  488.     If Not (moDPP Is Nothing) Then
  489.         moDPP.SetPeerInfo pInfo, DPNOP_SYNC
  490.     ElseIf Not (moDPC Is Nothing) Then
  491.         moDPC.SetClientInfo pInfo, DPNOP_SYNC
  492.     End If
  493.     mfDoneEnum = True
  494.  
  495.     With moHosts(lstGames.ItemData(lstGames.ListIndex)).AppDesc
  496.         dpApp.guidApplication = .guidApplication
  497.         dpApp.guidInstance = .guidInstance
  498.         mlNumPlayers = .lMaxPlayers
  499.     End With
  500.     
  501.     mfGotEvent = False
  502.     mfConnectComplete = False
  503.     'Lets get our host address
  504.     If moHosts(lstGames.ItemData(lstGames.ListIndex)).AddressHost <> vbNullString Then
  505.         Set HostAddr = moDX.DirectPlayAddressCreate
  506.         HostAddr.BuildFromURL moHosts(lstGames.ItemData(lstGames.ListIndex)).AddressHost
  507.     Else
  508.         Set HostAddr = moDPA
  509.     End If
  510.     If moHosts(lstGames.ItemData(lstGames.ListIndex)).AddressDevice <> vbNullString Then
  511.         Set DeviceAddr = moDX.DirectPlayAddressCreate
  512.         DeviceAddr.BuildFromURL moHosts(lstGames.ItemData(lstGames.ListIndex)).AddressDevice
  513.     Else
  514.         Set DeviceAddr = moDPA
  515.     End If
  516.     If Not (moDPP Is Nothing) Then
  517.         'Now we can join the selected session
  518.         moDPP.Connect dpApp, HostAddr, DeviceAddr, DPNCONNECT_OKTOQUERYFORADDRESSING, ByVal 0&, 0
  519.     ElseIf Not (moDPC Is Nothing) Then
  520.         'Now we can join the selected session
  521.         moDPC.Connect dpApp, HostAddr, DeviceAddr, DPNCONNECT_OKTOQUERYFORADDRESSING, ByVal 0&, 0
  522.     End If
  523.     Do While Not mfGotEvent 'Let's wait for our connectcomplete event
  524.         DoSleep 5 'Give other threads cpu time
  525.     Loop
  526.     If mfConnectComplete Then
  527.         'We've joined our game
  528.         mfComplete = True
  529.         mfHost = False
  530.         'Clean up our address
  531.         Set HostAddr = Nothing
  532.         Set DeviceAddr = Nothing
  533.         Set moDPA = Nothing
  534.         Unload Me
  535.     End If
  536. End Sub
  537.  
  538. Private Sub cmdOk_Click()
  539.     'They must specify a user name before we continue on to the next step
  540.     If txtUserName.Text = vbNullString Then
  541.         MsgBox "Please enter a username before going on.", vbOKOnly Or vbInformation, "No username"
  542.         Exit Sub
  543.     End If
  544.     sUser = txtUserName.Text
  545.     'Save the username
  546.     SaveSetting "VBDirectPlay", "Defaults", "UserName", sUser
  547.     SaveSetting "VBDirectPlay", "Defaults", "SPListIndex", lstSP.ListIndex
  548.     
  549.     If lstSP.ListIndex = lstSP.ListCount - 1 Then 'We want to wait for a lobby connection
  550.         moDPLA.SetAppAvailable True, 0
  551.         ShowPane WaitForLobby
  552.     Else
  553.         'Set up the address
  554.         Set moDPA = moDX.DirectPlayAddressCreate
  555.         If Not (moDPP Is Nothing) Then
  556.             moDPA.SetSP moDPP.GetServiceProvider(lstSP.ListIndex + 1).Guid
  557.         ElseIf Not (moDPC Is Nothing) Then
  558.             moDPA.SetSP moDPC.GetServiceProvider(lstSP.ListIndex + 1).Guid
  559.         End If
  560.         'Switch to the next screen
  561.         ShowPane CreateJoinGame
  562.     End If
  563. End Sub
  564.  
  565. Private Sub cmdOkCreate_Click()
  566.     sGameName = txtGameName.Text
  567.     If sGameName = vbNullString Then
  568.         MsgBox "You must enter a session name to create a session.", vbOKOnly Or vbInformation, "No name."
  569.         Exit Sub 'No need to continue
  570.     End If
  571.     If Val(txtUsers.Text) < 1 Then
  572.         MsgBox "You must enter a number of max players.", vbOKOnly Or vbInformation, "No max players."
  573.         Exit Sub 'No need to continue
  574.     End If
  575.     If Val(txtUsers.Text) > mlMax Then
  576.         MsgBox "The number of maximum players you specified exceeds the number of maximum players allowed in this session." & vbCrLf & "Please lower the number of your maximum players.", vbOKOnly Or vbInformation, "Too many players."
  577.         Exit Sub 'No need to continue
  578.     End If
  579.     mfHost = True
  580.     SaveSetting "VBDirectPlay", "Defaults", "GameName", sGameName
  581.     SaveSetting "VBDirectPlay", "Defaults", "HostMigrate", CStr(chkMigrate.Value)
  582.     If Not chkMigrate.Visible Then chkMigrate.Value = vbUnchecked
  583.     If Not CreateGame(sGameName, (chkMigrate.Value = vbChecked), Val(txtUsers.Text)) Then
  584.         MsgBox "Unable to create session", vbCritical Or vbOKOnly, "No session"
  585.         mfHost = False
  586.         ShowPane CreateJoinGame
  587.     Else
  588.         'We've created our game, load our game screen and wait for people to join
  589.         mfComplete = True
  590.         'Clean up our address
  591.         Set moDPA = Nothing
  592.         Unload Me
  593.     End If
  594.  
  595. End Sub
  596.  
  597. Private Sub cmdRefresh_Click()
  598.     
  599.     If mlSearch = StartSearch Then
  600.         'Time to enum our hosts
  601.         mfDoneEnum = False
  602.         Dim Desc As DPN_APPLICATION_DESC
  603.         Desc.guidApplication = msGuid
  604.         
  605.         If Not (moDPP Is Nothing) Then
  606.             mlEnumAsync = moDPP.EnumHosts(Desc, Nothing, moDPA, INFINITE, 0, INFINITE, DPNENUMHOSTS_OKTOQUERYFORADDRESSING, ByVal 0&, 0)
  607.         ElseIf Not (moDPC Is Nothing) Then
  608.             mlEnumAsync = moDPC.EnumHosts(Desc, Nothing, moDPA, INFINITE, 0, INFINITE, DPNENUMHOSTS_OKTOQUERYFORADDRESSING, ByVal 0&, 0)
  609.         End If
  610.         cmdRefresh.Caption = "Stop Search"
  611.         mlSearch = StopSearch
  612.     ElseIf mlSearch = StopSearch Then
  613.         mfDoneEnum = True
  614.         If Not (moDPP Is Nothing) Then
  615.             If mlEnumAsync <> 0 Then moDPP.CancelAsyncOperation mlEnumAsync, 0
  616.         ElseIf Not (moDPC Is Nothing) Then
  617.             If mlEnumAsync <> 0 Then moDPC.CancelAsyncOperation mlEnumAsync, 0
  618.         End If
  619.         cmdRefresh.Caption = "Start Search"
  620.         mlSearch = StartSearch
  621.     End If
  622. End Sub
  623.  
  624. Private Sub AddHostsToListBox(oHost As DPNMSG_ENUM_HOSTS_RESPONSE)
  625.     Dim lFound As Long
  626.     
  627.     'Here we will add a host that was found to our list box (or ignore it
  628.     'if it's already been added)
  629.     If mfDoneEnum Then Exit Sub
  630.     If mlHostCount = -1 Then
  631.         'We have no hosts already. Clear our list, and add this one to the list.
  632.         lstGames.Clear
  633.         ReDim moHosts(0)
  634.         moHosts(0).AppDesc = oHost.ApplicationDescription
  635.         moHosts(0).AddressHost = oHost.AddressSenderUrl
  636.         moHosts(0).AddressDevice = oHost.AddressDeviceUrl
  637.         'Save the last time this host was found
  638.         moHosts(0).TimeLastFound = GetTickCount
  639.         With oHost.ApplicationDescription
  640.             lstGames.AddItem .SessionName & " - " & CStr(.lCurrentPlayers) & "/" & CStr(.lMaxPlayers) & " - Latency:" & CStr(oHost.lRoundTripLatencyMS) & " ms"
  641.         End With
  642.         lstGames.ItemData(0) = 0
  643.         mlHostCount = mlHostCount + 1
  644.     Else
  645.         Dim lCount As Long
  646.         Dim fFound As Boolean
  647.         
  648.         For lCount = 0 To mlHostCount
  649.             If moHosts(lCount).AppDesc.guidInstance = oHost.ApplicationDescription.guidInstance Then
  650.                 'Save the last time this host was found
  651.                 moHosts(lCount).TimeLastFound = GetTickCount
  652.                 fFound = True
  653.                 Exit For
  654.             End If
  655.         Next
  656.         
  657.         If Not fFound Then 'We need to add this to the list
  658.             ReDim Preserve moHosts(mlHostCount + 1)
  659.             moHosts(mlHostCount + 1).AppDesc = oHost.ApplicationDescription
  660.             moHosts(mlHostCount + 1).AddressHost = oHost.AddressSenderUrl
  661.             moHosts(mlHostCount + 1).AddressDevice = oHost.AddressDeviceUrl
  662.             With oHost.ApplicationDescription
  663.                 lstGames.AddItem .SessionName & " - " & CStr(.lCurrentPlayers) & "/" & CStr(.lMaxPlayers) & " - Latency:" & CStr(oHost.lRoundTripLatencyMS) & " ms"
  664.             End With
  665.             'Save the last time this host was found
  666.             moHosts(mlHostCount + 1).TimeLastFound = GetTickCount
  667.             lstGames.ItemData(lstGames.ListCount - 1) = mlHostCount + 1
  668.             mlHostCount = mlHostCount + 1
  669.         Else 'We did find it, update the list
  670.             For lFound = 0 To lstGames.ListCount - 1
  671.                 With oHost.ApplicationDescription
  672.                 If lstGames.ItemData(lFound) = lCount Then 'This is it
  673.                     lstGames.List(lFound) = .SessionName & " - " & CStr(.lCurrentPlayers) & "/" & CStr(.lMaxPlayers) & " - Latency:" & CStr(oHost.lRoundTripLatencyMS) & " ms"
  674.                 End If
  675.                 End With
  676.             Next
  677.         End If
  678.     End If
  679. End Sub
  680.  
  681. 'We will handle all of the msgs here, and report them all back to the callback sub
  682. 'in case the caller cares what's going on
  683. Private Sub DirectPlay8Event_AddRemovePlayerGroup(ByVal lMsgID As Long, ByVal lPlayerID As Long, ByVal lGroupID As Long, fRejectMsg As Boolean)
  684.     'VB requires that we must implement *every* member of this interface
  685.     If (Not moCallback Is Nothing) Then moCallback.AddRemovePlayerGroup lMsgID, lPlayerID, lGroupID, fRejectMsg
  686. End Sub
  687.  
  688. Private Sub DirectPlay8Event_AppDesc(fRejectMsg As Boolean)
  689.     'VB requires that we must implement *every* member of this interface
  690.     If (Not moCallback Is Nothing) Then moCallback.AppDesc fRejectMsg
  691. End Sub
  692.  
  693. Private Sub DirectPlay8Event_AsyncOpComplete(dpnotify As DxVBLibA.DPNMSG_ASYNC_OP_COMPLETE, fRejectMsg As Boolean)
  694.     If dpnotify.AsyncOpHandle = mlEnumAsync Then mlEnumAsync = 0
  695.     'VB requires that we must implement *every* member of this interface
  696.     If (Not moCallback Is Nothing) Then moCallback.AsyncOpComplete dpnotify, fRejectMsg
  697. End Sub
  698.  
  699. Private Sub DirectPlay8Event_ConnectComplete(dpnotify As DxVBLibA.DPNMSG_CONNECT_COMPLETE, fRejectMsg As Boolean)
  700.     mfGotEvent = True
  701.     If dpnotify.hResultCode = DPNERR_SESSIONFULL Then 'Already too many people joined up
  702.         MsgBox "The maximum number of people allowed in this session have already joined.  Please choose a different session or create your own.", vbOKOnly Or vbInformation, "Full"
  703.         ShowPane CreateJoinGame
  704.     Else
  705.         'We got our connect complete event
  706.         mfConnectComplete = True
  707.         'VB requires that we must implement *every* member of this interface
  708.         If (Not moCallback Is Nothing) Then moCallback.ConnectComplete dpnotify, fRejectMsg
  709.     End If
  710. End Sub
  711.  
  712. Private Sub DirectPlay8Event_CreateGroup(ByVal lGroupID As Long, ByVal lOwnerID As Long, fRejectMsg As Boolean)
  713.     'VB requires that we must implement *every* member of this interface
  714.     If (Not moCallback Is Nothing) Then moCallback.CreateGroup lGroupID, lOwnerID, fRejectMsg
  715. End Sub
  716.  
  717. Private Sub DirectPlay8Event_CreatePlayer(ByVal lPlayerID As Long, fRejectMsg As Boolean)
  718.     'VB requires that we must implement *every* member of this interface
  719.     If (Not moCallback Is Nothing) Then moCallback.CreatePlayer lPlayerID, fRejectMsg
  720. End Sub
  721.  
  722. Private Sub DirectPlay8Event_DestroyGroup(ByVal lGroupID As Long, ByVal lReason As Long, fRejectMsg As Boolean)
  723.     'VB requires that we must implement *every* member of this interface
  724.     If (Not moCallback Is Nothing) Then moCallback.DestroyGroup lGroupID, lReason, fRejectMsg
  725. End Sub
  726.  
  727. Private Sub DirectPlay8Event_DestroyPlayer(ByVal lPlayerID As Long, ByVal lReason As Long, fRejectMsg As Boolean)
  728.     'VB requires that we must implement *every* member of this interface
  729.     If (Not moCallback Is Nothing) Then moCallback.DestroyPlayer lPlayerID, lReason, fRejectMsg
  730. End Sub
  731.  
  732. Private Sub DirectPlay8Event_EnumHostsQuery(dpnotify As DxVBLibA.DPNMSG_ENUM_HOSTS_QUERY, fRejectMsg As Boolean)
  733.     'VB requires that we must implement *every* member of this interface
  734.     If (Not moCallback Is Nothing) Then moCallback.EnumHostsQuery dpnotify, fRejectMsg
  735. End Sub
  736.  
  737. Private Sub DirectPlay8Event_EnumHostsResponse(dpnotify As DxVBLibA.DPNMSG_ENUM_HOSTS_RESPONSE, fRejectMsg As Boolean)
  738.     'Go ahead and add this to our list
  739.     AddHostsToListBox dpnotify
  740.     'VB requires that we must implement *every* member of this interface
  741.     If (Not moCallback Is Nothing) Then moCallback.EnumHostsResponse dpnotify, fRejectMsg
  742. End Sub
  743.  
  744. Private Sub DirectPlay8Event_HostMigrate(ByVal lNewHostID As Long, fRejectMsg As Boolean)
  745.     'VB requires that we must implement *every* member of this interface
  746.     If (Not moCallback Is Nothing) Then moCallback.HostMigrate lNewHostID, fRejectMsg
  747. End Sub
  748.  
  749. Private Sub DirectPlay8Event_IndicateConnect(dpnotify As DxVBLibA.DPNMSG_INDICATE_CONNECT, fRejectMsg As Boolean)
  750.     'VB requires that we must implement *every* member of this interface
  751.     If (Not moCallback Is Nothing) Then moCallback.IndicateConnect dpnotify, fRejectMsg
  752. End Sub
  753.  
  754. Private Sub DirectPlay8Event_IndicatedConnectAborted(fRejectMsg As Boolean)
  755.     'VB requires that we must implement *every* member of this interface
  756.     If (Not moCallback Is Nothing) Then moCallback.IndicatedConnectAborted fRejectMsg
  757. End Sub
  758.  
  759. Private Sub DirectPlay8Event_InfoNotify(ByVal lMsgID As Long, ByVal lNotifyID As Long, fRejectMsg As Boolean)
  760.     'VB requires that we must implement *every* member of this interface
  761.     If (Not moCallback Is Nothing) Then moCallback.InfoNotify lMsgID, lNotifyID, fRejectMsg
  762. End Sub
  763.  
  764. Private Sub DirectPlay8Event_Receive(dpnotify As DxVBLibA.DPNMSG_RECEIVE, fRejectMsg As Boolean)
  765.     'VB requires that we must implement *every* member of this interface
  766.     If (Not moCallback Is Nothing) Then moCallback.Receive dpnotify, fRejectMsg
  767. End Sub
  768.  
  769. Private Sub DirectPlay8Event_SendComplete(dpnotify As DxVBLibA.DPNMSG_SEND_COMPLETE, fRejectMsg As Boolean)
  770.     'VB requires that we must implement *every* member of this interface
  771.     If (Not moCallback Is Nothing) Then moCallback.SendComplete dpnotify, fRejectMsg
  772. End Sub
  773.  
  774. Private Sub DirectPlay8Event_TerminateSession(dpnotify As DxVBLibA.DPNMSG_TERMINATE_SESSION, fRejectMsg As Boolean)
  775.     'VB requires that we must implement *every* member of this interface
  776.     If (Not moCallback Is Nothing) Then moCallback.TerminateSession dpnotify, fRejectMsg
  777. End Sub
  778.  
  779. Private Sub DirectPlay8LobbyEvent_Connect(dlNotify As DxVBLibA.DPL_MESSAGE_CONNECT, fRejectMsg As Boolean)
  780.     Dim oDev As DirectPlay8Address, oHost As DirectPlay8Address
  781.     Dim oSetting As DPL_CONNECTION_SETTINGS
  782.     Dim pInfo As DPN_PLAYER_INFO
  783.     
  784.     On Local Error GoTo ErrOut
  785.     mlLobbyClientID = dlNotify.ConnectId
  786.     oSetting = moDPLA.GetConnectionSettings(mlLobbyClientID, 0)
  787.     'We were just connected to from a lobby
  788.     With oSetting
  789.     If Not (moDPP Is Nothing) Then
  790.         moDPP.RegisterLobby mlLobbyClientID, moDPLA, DPNLOBBY_REGISTER
  791.     ElseIf Not (moDPC Is Nothing) Then
  792.         moDPC.RegisterLobby mlLobbyClientID, moDPLA, DPNLOBBY_REGISTER
  793.     End If
  794.     'With ConnectionSettings
  795.     If .PlayerName <> vbNullString Then
  796.         sUser = .PlayerName
  797.         'Am I the host
  798.         If (.lFlags And DPLCONNECTSETTINGS_HOST) = DPLCONNECTSETTINGS_HOST Then
  799.             'Get the device address to host on
  800.             Set oDev = moDX.DirectPlayAddressCreate
  801.             oDev.BuildFromURL dlNotify.dplMsgCon.AddressSenderUrl
  802.             If Not CreateGameLobby(oDev, .ApplicationDescription) Then
  803.                 MsgBox "Unable to create session", vbCritical Or vbOKOnly, "No session"
  804.                 mfHost = False
  805.                 ShowPane CreateJoinGame
  806.             Else
  807.                 'We've created our game, load our game screen and wait for people to join
  808.                 mfHost = True 'We are the host
  809.                 mfComplete = True
  810.                 'Clean up our address
  811.                 Set moDPA = Nothing
  812.                 Unload Me
  813.             End If
  814.         Else 'we want to connect to an running app
  815.             sUser = .PlayerName
  816.             'Set up my peer info
  817.             pInfo.Name = sUser
  818.             pInfo.lInfoFlags = DPNINFO_NAME
  819.             'Go ahead and connect
  820.             Set oDev = moDX.DirectPlayAddressCreate
  821.             oDev.BuildFromURL dlNotify.dplMsgCon.AddressSenderUrl
  822.             Set oHost = moDX.DirectPlayAddressCreate
  823.             oHost.BuildFromURL dlNotify.dplMsgCon.AddressDeviceUrl
  824.             If Not (moDPP Is Nothing) Then
  825.                 moDPP.SetPeerInfo pInfo, DPNOP_SYNC
  826.                 'Connect now
  827.                 moDPP.Connect .ApplicationDescription, oHost, oDev, 0, ByVal 0&, 0
  828.             ElseIf Not (moDPC Is Nothing) Then
  829.                 moDPC.SetClientInfo pInfo, DPNOP_SYNC
  830.                 'Connect now
  831.                 moDPC.Connect .ApplicationDescription, oHost, oDev, 0, ByVal 0&, 0
  832.             End If
  833.             'Now we should wait until the connect complete event has fired
  834.             Do While Not mfConnectComplete
  835.                 DoEvents
  836.                 'We need to sleep here since the Directplay callbacks run on separate
  837.                 'threads, and a tight loop with only doevents will not allow them enough
  838.                 'time to call into VB.  Sleep 'pauses' this thread for a short time,
  839.                 'allowing the callbacks to process
  840.                 Sleep 10
  841.             Loop
  842.             'We've joined our game
  843.             mfComplete = True
  844.             mfHost = False
  845.             'Clean up our address
  846.             Set moDPA = Nothing
  847.             Unload Me
  848.             
  849.         End If
  850.     Else
  851.         ShowPane PickProtocol
  852.     End If
  853.     End With
  854.     Exit Sub
  855. ErrOut:
  856.     Debug.Print "Error:" & CStr(Err.Number) & " - " & Err.Description
  857. End Sub
  858.  
  859. Private Sub DirectPlay8LobbyEvent_ConnectionSettings(ConnectionSettings As DxVBLibA.DPL_MESSAGE_CONNECTION_SETTINGS)
  860.     'VB requires that we must implement *every* member of this interface
  861. End Sub
  862.  
  863. Private Sub DirectPlay8LobbyEvent_Disconnect(ByVal DisconnectID As Long, ByVal lReason As Long)
  864.     'VB requires that we must implement *every* member of this interface
  865. End Sub
  866.  
  867. Private Sub DirectPlay8LobbyEvent_Receive(dlNotify As DxVBLibA.DPL_MESSAGE_RECEIVE, fRejectMsg As Boolean)
  868.     'VB requires that we must implement *every* member of this interface
  869. End Sub
  870.  
  871. Private Sub DirectPlay8LobbyEvent_SessionStatus(ByVal status As Long, ByVal lHandle As Long)
  872.     'VB requires that we must implement *every* member of this interface
  873. End Sub
  874.  
  875. Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
  876.     If Not mfCanUnload Then Cancel = 1
  877.     Me.Hide
  878.     mfDoneWiz = True
  879. End Sub
  880.  
  881. Private Sub Form_Unload(Cancel As Integer)
  882.     'Clean up our lobbied app
  883.     If Not (moDPLA Is Nothing) Then
  884.         moDPLA.Close
  885.     End If
  886.     Set moDPLA = Nothing
  887.     'Clean up our address
  888.     Set moDPA = Nothing
  889. End Sub
  890.  
  891. Private Sub lstGames_DblClick()
  892.     cmdJoin_Click
  893. End Sub
  894.  
  895. Private Function CreateGame(ByVal sGameName As String, ByVal fHostMigrate As Boolean, ByVal lNumPlayers As Long) As Boolean
  896.     On Error GoTo ErrOut
  897.     
  898.     'We want to host our own game
  899.     Dim pInfo As DPN_PLAYER_INFO
  900.     Dim AppDesc As DPN_APPLICATION_DESC
  901.     
  902.     'Now set up the app description
  903.     With AppDesc
  904.         .guidApplication = msGuid
  905.         .lMaxPlayers = lNumPlayers
  906.         .SessionName = sGameName
  907.         If fHostMigrate Then
  908.             .lFlags = .lFlags Or DPNSESSION_MIGRATE_HOST
  909.         End If
  910.     End With
  911.     mlNumPlayers = lNumPlayers
  912.     'Set up my peer info
  913.     pInfo.Name = sUser
  914.     pInfo.lInfoFlags = DPNINFO_NAME
  915.     moDPP.SetPeerInfo pInfo, DPNOP_SYNC
  916.     
  917.     moDPP.Host AppDesc, moDPA, DPNHOST_OKTOQUERYFORADDRESSING
  918.     
  919.     CreateGame = True
  920.     
  921.     Exit Function
  922.  
  923. ErrOut:
  924.     CreateGame = False
  925.     Debug.Print "Error;"; Err; " - "; Err.Description
  926. End Function
  927.  
  928. Private Sub lstSP_DblClick()
  929.     cmdOk_Click
  930. End Sub
  931.  
  932. Public Property Get IsHost() As Boolean
  933.     IsHost = mfHost
  934. End Property
  935.  
  936. Public Property Get SessionName() As String
  937.     SessionName = sGameName
  938. End Property
  939.  
  940. Public Property Get UserName() As String
  941.     UserName = sUser
  942. End Property
  943.  
  944. Public Sub GoUnload()
  945.     tmrExpire.Enabled = False
  946.     mfCanUnload = True
  947.     Unload Me
  948. End Sub
  949.  
  950. Public Sub RegisterCallback(oCallback As DirectPlay8Event)
  951.     Set moCallback = oCallback
  952. End Sub
  953.  
  954. Public Property Get NumPlayers() As Long
  955.     NumPlayers = mlNumPlayers
  956. End Property
  957.  
  958. Private Sub ShowPane(ByVal lIndex As WizPanes)
  959.     'Here we will show the correct pane, and do whatever else
  960.     'we might need to do to get the step set up.
  961.     fraWiz(lIndex).ZOrder
  962.     Select Case lIndex
  963.     Case PickProtocol
  964.         cmdOk.Default = True
  965.         cmdCancel.Cancel = True
  966.         Me.Caption = App.EXEName & " - Choose Protocol"
  967.     Case CreateJoinGame
  968.         cmdCancelGame.Cancel = True
  969.         Me.Caption = App.EXEName & " - Create or Join Session"
  970.     Case CreateNewGame
  971.         cmdOkCreate.Default = True
  972.         cmdCancelCreate.Cancel = True
  973.         txtGameName.SetFocus
  974.         Me.Caption = App.EXEName & " - Create Session"
  975.     Case WaitForLobby
  976.         cmdCancelLobby.Cancel = True
  977.         cmdCancelLobby.Default = True
  978.         cmdCancelLobby.SetFocus
  979.         Me.Caption = App.EXEName & " - Wait for lobby connection"
  980.     End Select
  981. End Sub
  982.  
  983. Private Function CreateGameLobby(oHostAddr As DirectPlay8Address, newDesc As DPN_APPLICATION_DESC) As Boolean
  984.     On Error GoTo ErrOut
  985.     
  986.     'We want to host our own game
  987.     Dim pInfo As DPN_PLAYER_INFO
  988.     
  989.     'Set up my peer info
  990.     pInfo.Name = sUser
  991.     pInfo.lInfoFlags = DPNINFO_NAME
  992.     'We are only using the Peer object, since the client object *can't* host a session
  993.     moDPP.SetPeerInfo pInfo, DPNOP_SYNC
  994.     
  995.     newDesc.lFlags = newDesc.lFlags Or DPNSESSION_MIGRATE_HOST 'Turn on Migrate host by default
  996.     newDesc.lMaxPlayers = mlMax 'Let the max players join
  997.     sGameName = newDesc.SessionName
  998.     moDPP.Host newDesc, oHostAddr
  999.     CreateGameLobby = True
  1000.     
  1001.     Exit Function
  1002.  
  1003. ErrOut:
  1004.     CreateGameLobby = False
  1005.     Debug.Print "Error;" & CStr(Err.Number) & " - " & Err.Description
  1006. End Function
  1007.  
  1008. Private Sub RegisterThisApp(sGuid As String)
  1009.     Dim dplProg As DPL_PROGRAM_DESC
  1010.     'We need to register this program in case we aren't already registered
  1011.     With dplProg
  1012.         .ApplicationName = App.EXEName
  1013.         .Description = "VB DirectPlay SDK Sample"
  1014.         .ExecutableFilename = App.EXEName & ".exe"
  1015.         .ExecutablePath = App.Path
  1016.         .LauncherFilename = App.EXEName & ".exe"
  1017.         .LauncherPath = App.Path
  1018.         .guidApplication = sGuid
  1019.     End With
  1020.     moDPLA.RegisterProgram dplProg, 0
  1021. End Sub
  1022.  
  1023. Private Sub tmrExpire_Timer()
  1024.     
  1025.     'We need to periodically expire the hosts that are in this list in case they are
  1026.     'no longer hosting or what have you.
  1027.     Dim lCount As Long, lIndex As Long
  1028.     Dim lInner As Long
  1029.     
  1030.     On Error GoTo LeaveSub 'If there are no hosts, just go
  1031.     For lCount = 0 To UBound(moHosts)
  1032.         If (GetTickCount - moHosts(lCount).TimeLastFound) > HOST_EXPIRE_THRESHHOLD Then
  1033.             'Yup, this guy expired.. remove him from the list
  1034.             For lIndex = lstGames.ListCount - 1 To 0 Step -1
  1035.                 If lstGames.ItemData(lIndex) = lCount Then 'this is the one
  1036.                     lstGames.RemoveItem lIndex
  1037.                 End If
  1038.             Next
  1039.             moHosts(lCount).AddressDevice = vbNullString
  1040.             moHosts(lCount).AddressHost = vbNullString
  1041.             'Now we need an internal loop to 'remove' all of the old hosts info
  1042.             For lInner = lCount + 1 To UBound(moHosts)
  1043.                 moHosts(lInner - 1).AddressDevice = moHosts(lInner).AddressDevice
  1044.                 moHosts(lInner - 1).AddressHost = moHosts(lInner).AddressHost
  1045.                 moHosts(lInner - 1).AppDesc = moHosts(lInner).AppDesc
  1046.                 moHosts(lInner - 1).TimeLastFound = moHosts(lInner).TimeLastFound
  1047.             Next
  1048.             'Now we need to decrement each of the remaining items in the listbox
  1049.             For lIndex = lstGames.ListCount - 1 To 0 Step -1
  1050.                 If lstGames.ItemData(lIndex) > lCount Then 'decrement this one
  1051.                     lstGames.ItemData(lIndex) = lstGames.ItemData(lIndex) - 1
  1052.                 End If
  1053.             Next
  1054.             mlHostCount = mlHostCount - 1
  1055.             If UBound(moHosts) > 0 Then
  1056.                 ReDim Preserve moHosts(UBound(moHosts) - 1)
  1057.             Else
  1058.                 Erase moHosts 'This will just erase the memory
  1059.             End If
  1060.         End If
  1061.     Next
  1062. LeaveSub:
  1063. End Sub
  1064.  
  1065.